`include "cpu_def.vh"

module pc(
  input         clk,
  input         rst,

  input        frontend_redirect_taken,
  input [31:0] frontend_redirect_pc,

  input        backend_redirect_taken,
  input [31:0] backend_redirect_pc,
  input        pc_stall   ,

  // to mmu
  output instr_vaddr_valid,
  output [31:0] instr_vaddr,
  output itlb0_flush,
  output itlb0_stall,

  input instr_paddr_valid,

  // to isram_like_wrap
  output        valid_o ,
  output [31:0] vaddr_o 
);

  reg valid;
  reg  [31:0] pc_r;
  wire [31:0] pc_next;
  wire [31:0] pc_seq;

  assign pc_next = 
    backend_redirect_taken ? backend_redirect_pc :
    pc_stall ? pc_r :
    frontend_redirect_taken ? frontend_redirect_pc :
    !instr_paddr_valid ? pc_r : pc_seq;
  assign pc_seq = {pc_r[31:4] + 1, 4'd0};

  always@(posedge clk) begin
    if(rst) begin
      valid <= 1'b0;
    end else begin
      valid <= 1'b1;
    end
  end

  always@(posedge clk) begin
    if (rst) begin
      pc_r <= `START_POINT;
    end else begin
      pc_r <= pc_next;
    end
  end

  assign instr_vaddr_valid = valid;
  assign instr_vaddr = pc_r;
  assign itlb0_flush = frontend_redirect_taken || backend_redirect_taken;
  assign itlb0_stall = pc_stall;

  assign valid_o = valid && instr_paddr_valid;
  assign vaddr_o = pc_r;

endmodule